﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using log4net;

namespace SyncLib
{
    public class AppLock
    {
        static ILog Log = LogManager.GetLogger(typeof(Log4NetImplement));

        public AppLock()
        {

            //Current = this;
        }
        static AppLock()
        {
            monitor = new Mutex(false, "KeeperSyncMutextV1");
        }

        public static Guid CurrentClient { get; private set; }
        private static DateTime LastActivityOfCurrentClient { get; set; }
        //ManualResetEvent monitor;
        static Mutex monitor;
        public static bool SetClient(Guid id, int timeout)
        {
            bool flag = false;
            try
            {
                Log.InfoFormat("ClientId \"{0}\" Cal SetClient ", id);
                Log.InfoFormat("    Current ClientId \"{0}\" Last Activity {1:dd/MM/yyyy HH:mm:ss,ffff}", CurrentClient, LastActivityOfCurrentClient);
                if (monitor.WaitOne(timeout * 100))
                {
                    flag = true;
                    Log.InfoFormat("      WaitOne {0} ms return True", timeout);
                    if (CurrentClient.Equals(Guid.Empty) || CurrentClient.Equals(id))
                    {
                        Log.Info("End SetClient(Success)");
                        CurrentClient = id;
                        return true;
                    }
                    else
                    {
                        TimeSpan ts = DateTime.Now.Subtract(LastActivityOfCurrentClient);
                        if (ts.TotalMinutes > 30)
                        {
                            Log.InfoFormat("CurrentID \"{0}\" has Idle for {1} minute. Set new CurrentId=\"{2}\""
                                , CurrentClient, ts.TotalMinutes, id);
                            Log.Info("End SetClient(Success)");
                            CurrentClient = id;
                            return true;
                        }


                    }

                }
                Log.Info("End SetClient(Fail)");
                return false;
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (flag)
                    monitor.ReleaseMutex();
            }
        }
        public static void KeepAlive(Guid id)
        {
            monitor.WaitOne();
            try
            {
                Log.InfoFormat("ClientId \"{0}\" call KeepAlive.", id);
                Log.InfoFormat("    Current ClientId \"{0}\" Last Activity {1:dd/MM/yyyy HH:mm:ss,ffff}", CurrentClient, LastActivityOfCurrentClient);
                if (CurrentClient.Equals(id))
                {
                    Log.InfoFormat("    Current ClientId \"{0}\" New Last Activity {1:dd/MM/yyyy HH:mm:ss,ffff}", CurrentClient, LastActivityOfCurrentClient);

                    LastActivityOfCurrentClient = DateTime.Now;
                }
            }
            finally
            {
                Log.InfoFormat("End KeepAlive");
                monitor.ReleaseMutex();
            }
        }
        public static bool ResetClient(Guid id)
        {
            bool flag = false;
            try
            {
                Log.InfoFormat("ClientId \"{0}\" call ResetClient.", id);
                Log.InfoFormat("    Current ClientId \"{0}\" Last Activity {1:dd/MM/yyyy HH:mm:ss,ffff}", CurrentClient, LastActivityOfCurrentClient);

                if (monitor.WaitOne(1000 * 100))
                {
                    flag = true;
                    if (CurrentClient.Equals(id))
                    {
                        Log.InfoFormat("    CurrentClient was reset to Empty");
                        CurrentClient = Guid.Empty;
                        LastActivityOfCurrentClient = DateTime.Now;
                        return true;
                    }
                }
                return false;
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (flag)
                    monitor.ReleaseMutex();
            }

        }
    }
}
